import React, {
  FC,
  MouseEventHandler,
  useCallback,
  useEffect,
  useMemo,
  useReducer,
  useRef,
  useState,
} from "react";
import { Button, Space } from "antd";
import { find, get, isArray } from "lodash";

const BaseSize = 500;
enum ActionStatus {
  "查看",
  "缩放",
  "绘图",
}

const SourcePos: FC<{
  source: any;
  roi?: [number, number][]
  getInfo?: (v: any, posInfo: { top: number, left: number, width: number, height: number }) => void;
}> = ({ source, getInfo, roi }) => {
  const [actionStatus, setActionStatus] = useState<ActionStatus>(
    ActionStatus.查看
  );
  const imgRef = useRef<HTMLImageElement>(null);
  const posRef = useRef({
    elX: 0,
    elY: 0,
    startX: 0,
    startY: 0,
    width: 0,
    height: 0,
  });
  const [key, uploadCompKey] = useReducer((v) => v + 1, 0);
  const offsetRef = useRef({
    offsetX: 0,
    offsetY: 0,
  });
  const scaleRef = useRef(1);
  const contRef = useRef<HTMLDivElement>(null);
  useEffect(() => {
    if (get(roi, 'length', 0) === 0) return;
    const startX = roi?.reduce((cur, [x]) => Math.min(cur, x), Infinity)
    const startY = roi?.reduce((cur, [, y]) => Math.min(cur, y), Infinity)
    const width = roi?.reduce((cur, [x]) => Math.max(cur, x - startX), 0)
    const height = roi?.reduce((cur, [, y]) => Math.max(cur, y - startY), 0)
    posRef.current.startX = startX / scaleRef.current
    posRef.current.startY = startY / scaleRef.current
    posRef.current.width = width / scaleRef.current
    posRef.current.height = height / scaleRef.current
    uploadCompKey()
  }, [roi])
  const posStyle = useMemo(() => {
    return {
      left: posRef.current.startX,
      top: posRef.current.startY,
      width: posRef.current.width,
      height: posRef.current.height,
    };
  }, [key]);

  useEffect(() => {
    const { left, top, width, height } = posStyle;
    const scale = scaleRef.current;
    getInfo?.([
      [left, top],
      [left, (top + height)],
      [(left + width), (top + height)],
      [(left + width), top],
    ], {
      top,left, width, height
    });
  }, [posStyle]);

  const imgStyle = useMemo(() => {
    const style: React.CSSProperties = {
      transform: `scale(${scaleRef.current}) translate3d(${offsetRef.current.offsetX}px, ${offsetRef.current.offsetY}px, 0)`,
    };
    return style;
  }, [key]);

  useEffect(() => {
    if (!contRef.current) return;
  }, []);

  const mouseAttrRef = useRef({
    isMouse: false,
    mouseX: 0,
    mouseY: 0,
  });

  const onContMouseMove = useCallback<MouseEventHandler<any>>(
    (e) => {
      if (!mouseAttrRef.current.isMouse) return;
      const { mouseY, mouseX } = mouseAttrRef.current;
      const x = mouseX - e.screenX;
      const y = mouseY - e.screenY;
      if ([ActionStatus.缩放, ActionStatus.查看].includes(actionStatus)) {
        offsetRef.current = {
          offsetX: offsetRef.current.offsetX - x,
          offsetY: offsetRef.current.offsetY - y,
        };
      }
      if (actionStatus === ActionStatus.绘图) {
        posRef.current = {
          ...posRef.current,
          width:
            (e.clientX - posRef.current.elX) / scaleRef.current -
            Math.abs(posRef.current.startX),
          height:
            (e.clientY - posRef.current.elY) / scaleRef.current -
            Math.abs(posRef.current.startY),
        };
      }
      uploadCompKey();
      mouseAttrRef.current = {
        ...mouseAttrRef.current,
        mouseX: e.screenX,
        mouseY: e.screenY,
      };
    },
    [actionStatus]
  );
  const onMouseCancel = useCallback<MouseEventHandler<any>>(
    (e) => {
      if (!mouseAttrRef.current.isMouse) return;
      onContMouseMove(e);
      mouseAttrRef.current = {
        ...mouseAttrRef.current,
        isMouse: false,
      };
      document.body.removeEventListener("mousemove", onContMouseMove);
      document.body.removeEventListener("mouseup", onMouseCancel);
    },
    [onContMouseMove]
  );
  const onContMouseDown = useCallback<MouseEventHandler<any>>(
    (e) => {
      e.preventDefault();
      e.stopPropagation();
      mouseAttrRef.current = {
        isMouse: true,
        mouseX: e.screenX,
        mouseY: e.screenY,
      };
      if (actionStatus === ActionStatus.绘图 && imgRef.current) {
        const { x, y } = imgRef.current.getBoundingClientRect();
        posRef.current = {
          ...posRef.current,
          elX: x,
          elY: y,
          startX: (e.clientX - x) / scaleRef.current,
          startY: (e.clientY - y) / scaleRef.current,
          width: 0,
          height: 0,
        };
      }
      document.body.addEventListener("mousemove", onContMouseMove);
      document.body.addEventListener("mouseup", onMouseCancel);
    },
    [actionStatus]
  );
  const contStyle = useMemo(() => {
    const result: React.CSSProperties = {};
    if ([ActionStatus.缩放, ActionStatus.查看].includes(actionStatus)) {
      result.cursor = "move";
    }
    return result;
  }, [actionStatus]);
  return (
    <div>
      <div
        className="relative h-[500px] w-[500px] overflow-hidden overflow-hidden"
        ref={contRef}
        onMouseDown={onContMouseDown}
        onWheel={(e) => {
          e.stopPropagation();
          e.preventDefault();
          if ([ActionStatus.缩放].includes(actionStatus)) {
            scaleRef.current =
              Math.max(0, scaleRef.current + Math.min(Math.max(e.deltaY, -2), 2) / 100);
            uploadCompKey();
          }
        }}
        style={contStyle}
      >
        <div className="absolute top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]">
          <div style={imgStyle} className="relative" ref={imgRef}>
            <img
              src={source}
              onLoad={(e) => {
                const { width, height } = e.target;
                // scaleRef.current =
                //   width > height ? BaseSize / width : BaseSize / height;

                e.target.style.width = width + 'px'
                e.target.style.height = height + 'px'
              }}
              className="select-none"
            />
            <div
              className="absolute box-border border-2 border-solid border-[red]"
              style={posStyle}
            />
          </div>
        </div>
      </div>
      <Space className="">
        <Button
          type={ActionStatus.缩放 === actionStatus ? "primary" : "default"}
          onClick={() => {
            setActionStatus(ActionStatus.缩放);
          }}
        >
          缩放
        </Button>
        <Button
          type={ActionStatus.绘图 === actionStatus ? "primary" : "default"}
          onClick={() => {
            setActionStatus(ActionStatus.绘图);
          }}
        >
          拉框
        </Button>
      </Space>
    </div>
  );
};

export default SourcePos;
